﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ZGSharp.Optimeters;

namespace ZGSharp
{
	public enum TensorKinds
	{
		TensorNormal,
		TensorConst,
		LayerLinear,
		LayerConv2D,
		LayerDropout,
		LayerRelu,
		LayerSigmoid,
		LayerSoftmax,
		LayerReduceMean,
		LayerReduceSum,
		LayerMaxPool2D,
		LayerReduceMax,
		LayerOperatorAdd,
		LayerOperatorMinus,
		LayerOperatorMultiply,
		LayerOperatorDivide,
		LayerOperatorPow,
		LayerOperatorLog
	}
	public class CommonDef
	{
		internal static string GetBase64(double[] weights)
		{
			if (weights == null) 
			{
				return "";
			}
			List<byte> listSave = new List<byte>();
			for (int i = 0; i < weights.Length; i++)
			{
				listSave.AddRange(BitConverter.GetBytes(weights[i]));
			}
			return Convert.ToBase64String(listSave.ToArray(), Base64FormattingOptions.None);
		}

		public static OptBase Opt = new SGD();

        internal static Dictionary<string, string> GetSaveMsgDic(string v)
        {
			Dictionary<string, string> dic = new Dictionary<string, string>();
			string[] items = v.Split(',');
			foreach (string item in items) 
			{
				string[] key_value = item.Split(':');
				dic.Add(key_value[0].Trim('\n'), key_value[1].Trim('\n'));
			}
			return dic;
        }

        internal static double[] GetDataFromBase64(string v)
        {
			byte[] data = Convert.FromBase64String(v);
			List<double> listNumber = new List<double>();
			for (int i = 0; i < data.Length / 8; i++) 
			{
				listNumber.Add(BitConverter.ToDouble(data, i * 8));
			}
			return listNumber.ToArray();
        }

		public static Tensor GetOneHot(int[] list, int arry_len)
		{
			double[] onehot = new double[list.Length * arry_len];
			Parallel.For(0, list.Length, i => {
				onehot[i * arry_len + list[i]] = 1;
			});
			Tensor onehot_tensor = Tensor.ToTensor(new int[] { list.Length, arry_len }, onehot);
			return onehot_tensor;
		}

        public static double GetAccuracy(Tensor pred, int[] label_data)
        {
			int counter = 0;
			for (int i = 0; i < pred.batch_size; i++) 
			{
				int result = pred.GetMaxIndexInBatch(i);
				if (result == label_data[i]) 
				{
					counter++;
				}
			}
			return counter * 1.0 / pred.batch_size;
        }
    }
}